﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace AgvPublic
{
    public class ClientTcp
    {
        public delegate void AgvInfoTcpDelegate(string ip, byte[] buffer);
        public event AgvInfoTcpDelegate AgvInfoTcpEvent;


        public delegate void SocketReconnectDele();
        public event SocketReconnectDele socketReconnectHandle;//

        public delegate void ClientTcpDelegate(string ip, ClientTcp ct);
        public event ClientTcpDelegate ClientTcpEvent;


        public const int BufferSize = 1024;
        public byte[] bufferAgv = new byte[BufferSize];
        private string remoteHost = "";
        private int remotePort = 0;
        IPEndPoint ipPort;
        /// <summary>
        /// 客户端使用的异步socket
        /// </summary>
        private Socket _clientSock;
        public ClientTcp(string ip, int port)
        {
            remoteHost = ip;
            remotePort = port;
            socketReconnectHandle += TcpClient_socketReconnectHandle;
         
        }

        private void TcpClient_socketReconnectHandle()
        {
            Connect();
        }

    
        public void Start()
        {
            IPEndPoint ipPort = new IPEndPoint(IPAddress.Parse(remoteHost), remotePort);
            _clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _clientSock.BeginConnect(ipPort, new AsyncCallback(ConnectedCallback), _clientSock); 
          
        }

        public void ConnectedCallback(IAsyncResult iar)
        {

            Socket client = (Socket)iar.AsyncState;
            try
            {
              
                    string ip = client.RemoteEndPoint.ToString().Split(':')[0];
                    client.EndConnect(iar);
                    ClientTcpEvent(ip, this);
                     
                    client.BeginReceive(bufferAgv, 0, bufferAgv.Length, SocketFlags.None,
                                       new AsyncCallback(ReceivedCallback), client);
             
            }
            catch (SocketException ex)
            {
                if (socketReconnectHandle != null)
                {
                    socketReconnectHandle();
                }
            }
            catch (ObjectDisposedException ex)
            {
                if (socketReconnectHandle != null)
                {
                    socketReconnectHandle();
                }
            }
            catch (ArgumentException ex)
            {
                //已释放异常
                if (socketReconnectHandle != null)
                {
                    socketReconnectHandle();
                }
            }
            catch (InvalidOperationException ex)
            {
                //已释放异常
                if (socketReconnectHandle != null)
                {
                    socketReconnectHandle();
                }
            }
            //finally
            //{
            //}
        }


        public void ReceivedCallback(IAsyncResult iar)
        {
            Socket client = (Socket)iar.AsyncState;
            try
            {
                if (client != null && client.Connected)
                {
                    int recv = client.EndReceive(iar);
                    if (recv > 0)
                    {
                        string ip = client.RemoteEndPoint.ToString().Split(':')[0];
                        AgvInfoTcpEvent(ip, bufferAgv);
                        client.BeginReceive(bufferAgv, 0, bufferAgv.Length, SocketFlags.None,
                                   new AsyncCallback(ReceivedCallback), client);
                    }
                  
                }

            }
            catch (SocketException ex)
            {
               //套接字异常
            }
            catch (ObjectDisposedException ex)
            {
               //已释放异常
            }
            catch (ArgumentException ex)
            {
                //已释放异常
            }
            catch (InvalidOperationException ex)
            {
                //已释放异常
            }
        }


        public void Connect()
        {
            
                if (_clientSock != null)
                {
                   
                    try
                    {
                        _clientSock.Close();
                    }
                    catch
                    { }

                }
           


           
                IPEndPoint ipPort = new IPEndPoint(IPAddress.Parse(remoteHost), remotePort);
                _clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _clientSock.BeginConnect(ipPort, new AsyncCallback(ConnectedCallback), _clientSock);
         

        }

        public void Reconnect()
        {
            try
            {
                if (_clientSock != null)// && _clientSock.Connected 
                {
                    try
                    {
                        _clientSock.Shutdown(SocketShutdown.Both);
                    }
                    catch (SocketException ex)
                    {
                        //套接字异常
                    }
                    catch (ObjectDisposedException ex)
                    {
                        //已释放异常
                    }        

                    try
                    {
                        _clientSock.Close();
                    }
                    catch
                    { }
                }
            }
            catch
            { }


          
                IPEndPoint ipPort = new IPEndPoint(IPAddress.Parse(remoteHost), remotePort);
                _clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _clientSock.BeginConnect(ipPort, new AsyncCallback(ConnectedCallback), _clientSock);
          
        }

        public void Send(string msg)
        {

            if (_clientSock == null || msg == string.Empty)
                return;

            msg += "\r\n";

            byte[] data = Encoding.UTF8.GetBytes(msg);
            try
            {
                _clientSock.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
                {
                    if (_clientSock != null && _clientSock.Connected)
                    {
                        int length = _clientSock.EndSend(asyncResult);
                    }
                    
                    //OnSend(string.Format("客户端发送消息:{0}", msg));
                }, _clientSock);
            }
            catch (SocketException ex)
            {
                //套接字异常
            }
            catch (ObjectDisposedException ex)
            {
                //已释放异常
            }
            catch (ArgumentException ex)
            {
                //已释放异常
            }
            catch (InvalidOperationException ex)
            {
                //已释放异常
            }
        }

        public void Send(byte[] data)
        {

            if (_clientSock == null)
                return;

            try
            {
                _clientSock.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
                {
                    if (_clientSock != null && _clientSock.Connected)
                    {
                        _clientSock.EndSend(asyncResult);
                    }
                    //OnSend(string.Format("客户端发送消息:{0}", msg));
                }, _clientSock);
            }
            catch (SocketException ex)
            {
                //套接字异常
            }
            catch (ObjectDisposedException ex)
            {
                //已释放异常
            }
            catch (ArgumentException ex)
            {
                //已释放异常
            }
            catch (InvalidOperationException ex)
            {
                //已释放异常
            }
          
        }
    }
}
